﻿using System;
using System.Collections.Generic;
using System.Text;
using PhiStore;
using System.Diagnostics;
using System.Collections;
using PhiStore.Packages;
using PhiStore.Threading;

namespace PhiStore.Storage
{
    internal class StorageManager
    {
        List<IStorageDevice> devices;

        private static StorageManager instance = null;

        private object mutex = new object();

        private StorageManager()
        {
            LoadSettings();
        }

        public static StorageManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new StorageManager();
                }
                return instance;
            }
        }

        ////for testing purposes - exclude once finished - not MONO-compliant
        //public T GetStorage<T>(){
            
        //    T result = default(T);
        //    foreach (IStorageDevice dev in devices)
        //    {
        //        if (dev.GetType() == typeof(T))
        //        {
        //            result = (T)dev;
        //        }
        //    }
        //    return result;
        //}

        public IStorageDevice[] Devices
        {
            get
            {
                lock (mutex)
                {
                    return devices.ToArray();
                }
            }
        }

        public bool Add(IStorageDevice device)
        {
            bool result = false;
            if (device.Works())
            {
                lock (mutex)
                {
                    if (!devices.Contains(device))
                        devices.Add(device);

                    SaveSettings();
                    result = true;
                    if (toObjectManager != null && !toObjectManager.IsPoisoned)
                    {
                        toObjectManager.Send(new DeviceAdded(device));
                    }
                }
            }
            return result;
        }

        public void Remove(IStorageDevice device)
        {
            lock (mutex)
            {
                PhiServer.Instance.Stop();

                if (devices.Contains(device))
                    devices.Remove(device);

                SaveSettings();
            }
        }

        public bool ReadyToRun
        {
            get
            {
                bool result = true;
                lock (mutex)
                {
                    foreach (IStorageDevice device in devices)
                    {
                        result &= device.Works();
                    }
                }

                return result;
            }
        }

        private void LoadSettings()
        {
            try
            {
                devices = SettingsManager.Instance.Read<List<IStorageDevice>>("StorageDevices");
            }
            catch
            {
                devices = new List<IStorageDevice>();
            }
        }

        private void SaveSettings()
        {
            SettingsManager.Instance.Add("StorageDevices", devices);
        }

        private Channel<PhiInternalPackage> toObjectManager = null;
        public void RegisterObjectManager(Channel<PhiInternalPackage> toObjectManager)
        {
            this.toObjectManager = toObjectManager;
            foreach (IStorageDevice device in devices)
            {
                toObjectManager.Send(new DeviceAdded(device));
            }
        }

        internal void ClearDevices()
        {
            foreach (IStorageDevice device in devices)
            {
                List<string> paths = device.GetPaths();
                foreach (string path in paths)
                {
                    if (path.EndsWith(device.DirectorySeperator))
                    {
                        device.DeleteDirectory(path);
                    }
                }
            }
        }
    }
}
